package com.oromwin.repos.server.request.media;

import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.util.List;

import org.apache.commons.logging.Log;

import com.oromwin.repos.common.Common;
import com.oromwin.repos.common.Logger;
import com.oromwin.repos.common.ReposException;
import com.oromwin.repos.common.Server;
import com.oromwin.repos.common.helper.DBHelper;
import com.oromwin.repos.common.helper.FSHelper;
import com.oromwin.repos.common.helper.IOHelper;
import com.oromwin.repos.data.AbstractReposTable;
import com.oromwin.repos.data.MediaTable;
import com.oromwin.repos.data.VolumeTable;
import com.oromwin.repos.server.LockObject;
import com.oromwin.repos.server.request.AbstractRequest;
import com.oromwin.repos.server.response.CreateResponse;
import com.oromwin.repos.server.response.Response;

public class CreateMediaRequest extends AbstractRequest {
    private Log log = Logger.getLog(CreateMediaRequest.class);
    private String VolumeId = null;
    private File MediaPath = null;
    private Long MediaMaxBytes = 0L;
    
    @Override
    public void receive(DataInputStream dis, LockObject lockObject) throws ReposException {
        try {
            VolumeId = IOHelper.readUTF8(dis);
            MediaPath = new File(IOHelper.readUTF8(dis));
            MediaMaxBytes = dis.readLong();
        } catch (IOException e) {
            throw ReposException.create(log, e);
        }
    }

    @Override
    public Response run() throws ReposException {
        CreateResponse res = null;
        try {
            getCurrentReposTables();
            checkDependentObjectNotExists();
            checkSameObjectExists();
            checkFreeSpaceExists();
            _mediaTable = new MediaTable(_volumeTable.getVolumeId(), id(), MediaPath, MediaMaxBytes, 0L, 0, Boolean.FALSE, Common.datetime(), Common.datetime());
            DBHelper.insertTable(_mediaTable);
            res = new CreateResponse(true, "Succeeded to create media", id());
        } catch (ReposException e) {
            res = new CreateResponse(false, e.getMessage(), id());
        } catch (Exception e) {
            String message = String.format("Unexpected exception, {%s}", e.getMessage());
            throw ReposException.create(log, e, message);
        }
        return res;
    }
    
    @Override
    public void getCurrentReposTables() throws ReposException {
        // 1. 볼륨정보를 가져옴
        AbstractReposTable reposTable = null;
        String whereClause = String.format("VolumeStatus = 0 AND VolumeId = '%s'", VolumeId);
        List<AbstractReposTable> reposTables = DBHelper.selectTable(VolumeTable.class, whereClause);
        if (reposTables != null && reposTables.size() == 1) {
            reposTable = reposTables.get(0);
        } else {
            String message = String.format("'%s' VolumeId does not exists in database, tableSize:whereClause {%d:%s}", VolumeId, reposTables.size(), whereClause);
            throw ReposException.create(log, message); 
        }
        if (reposTable instanceof VolumeTable) {
            _volumeTable = (VolumeTable) reposTable;
        } else {
            String message = String.format("Illegal volume table type, class {%s}", reposTable.getClass().toString());
            throw ReposException.create(log, message);
        }
    }
    
    @Override 
    public void checkDependentObjectNotExists() throws ReposException {
        // 1. 미디어 경로  생성
        if (FSHelper.ls(MediaPath)) {
            String message = String.format("'%s' MediaPath already exists on the server", MediaPath);
            if (log.isWarnEnabled()) log.warn(message);
        } else {
            FSHelper.mkdir(MediaPath);
        }
    }
    
    @Override
    public void checkSameObjectExists() throws ReposException {
        // 1. 데이터베이스에 동일한 경로의 미디어레코드가 있으면 오류 
        String whereClause = String.format("MediaPath = '%s' AND MediaStatus = 0", MediaPath);
        List<AbstractReposTable> list = DBHelper.selectTable(MediaTable.class, whereClause);
        if (list.size() > 0) {
            String message = String.format("'%s' MediaPath already exists in database, VolumeId {%s}", MediaPath, VolumeId);
            throw ReposException.create(log, message); 
        }
    }

    @Override
    public void checkFreeSpaceExists() throws ReposException {
        Long requestedBytes = MediaMaxBytes;
        Long freeSpace = Server.freeSpace(MediaPath);
        if (freeSpace < requestedBytes) {
            String message = String.format("Not enough disk space available, spaceAvailable:requestedBytes {%d:%d}", freeSpace, requestedBytes);
            throw ReposException.create(log, message); 
        }
    }
}
